package com.wanban.adutils.advertisers

import android.app.Activity
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.google.android.gms.ads.LoadAdError
import com.wanban.adutils.AdUtils
import com.wanban.adutils.R
import com.wanban.adutils.callback.OnLoadAdCallback
import com.wanban.adutils.db.bean.AdInfo
import com.wanban.adutils.tools.AdConstants
import com.wanban.adutils.tools.RxUtils
import com.wanban.adutils.tools.Tools
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import java.util.concurrent.TimeUnit


abstract class BaseAdLoader {
    // 永远不会为空
    private var timeoutDisposable: Disposable? = null
    private var countDownDisposable: Disposable? = null

    // 是否已经超时
    var isTimeout = false
    private var timeout = 0
    // 广告是否再整显示
    private var isAdShowing = false
    // 广告SDK反馈加载回调
    private var isAdSDKCallback = false
    // 广告加载成功，执行onAdLoaded
    private var isAdLoadSuccess = false
    // 广告id
    protected var realUnitId: String = ""
    private var showTime = AdConstants.AD_DEFAULT_SHOW_TIME
    var mOnLoadAdCallback: OnLoadAdCallback? = null


    open fun loadAdNew(activity: Activity, adInfo: AdInfo, callback: OnLoadAdCallback) {
        val adName = AdUtils.getAdNameByType(adInfo.adId)
        if (isActivityNotActive(activity)) {
            Log.e(AdConstants.TAG, "$adName -> BaseAdLoader -> activity已经失效...")
            callback.onAdLoadFailed(AdConstants.ERROR_CODE_ACTIVITY_NOT_ACTIVE)
            destroy()
            return
        }
        Log.e(AdConstants.TAG, "$adName -> BaseAdLoader -> 真正开始请求广告...")
        isAdShowing = false
        isAdSDKCallback = false
        isAdLoadSuccess = false
        // 超时时间
        timeout = adInfo.timeout
        // 插播广告显示时间
        showTime = adInfo.ad_duration
        // 广告id
        realUnitId = AdUtils.getUnitId(adInfo)
        // 设置广告回调
        mOnLoadAdCallback = callback
        // 设置超时反馈
        timeoutControllerNew(activity, adName, callback)
    }


    private fun timeoutControllerNew(activity: Activity, adName: String, callback: OnLoadAdCallback) {
        if (timeout <= 0) {
            Log.e(AdConstants.TAG, "$adName -> BaseAdLoader -> 关闭了超时时间监控...")
            return
        }
        Log.e(AdConstants.TAG, "$adName -> BaseAdLoader -> 启动超时时间监控...")
        timeoutDisposable = RxUtils.timer(timeout * 1000L) {
            Log.e(AdConstants.TAG, "$adName -> BaseAdLoader -> 广告请求超时...")
            if (isAdSDKCallback) { // 广告已经结束，此时超时没意义，不需要通知前端
                isAdSDKCallback = false
            } else { // 广告超时
                isTimeout = true
                Log.e(AdConstants.TAG, "$adName -> BaseAdLoader -> 反馈前端超时...")
                if (isActivityNotActive(activity)) return@timer
                activity.runOnUiThread {
                    callback.onAdLoadFailed(AdConstants.ERROR_CODE_AD_OUT_OF_TIME)
                }
            }
        }
    }

    protected open fun sdkLoadFinish() {
        isAdSDKCallback = true
        isTimeout = false
        if (timeoutDisposable != null && timeoutDisposable?.isDisposed == false) {
            timeoutDisposable?.dispose()
        }
    }

    fun setAdLoadSuccess(){
        isAdLoadSuccess = true
    }

    open fun isAdLoadSuccess(): Boolean {
        return isAdLoadSuccess
    }

    fun setAdLoadShowing(isAdShowing: Boolean){
        this.isAdShowing = isAdShowing
    }
    fun isAdShowing(): Boolean {
        return isAdShowing
    }

    open fun showAd(adRoot: ViewGroup, type: Int = -1) {
        if (mOnLoadAdCallback == null) return
        val activity = Tools.findActivity(adRoot.context)
        if (isActivityNotActive(activity)) {
            mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_ACTIVITY_DESTROYED)
            return
        }
        if (!isAdLoadSuccess()) {
            mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_ACTIVITY_DESTROYED)
            destroy()
            return
        }
        if (isAdShowing()) {
            mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_AD_IS_SHOWING)
            return
        }
    }

    open fun showAd(activity: Activity) {
        if (mOnLoadAdCallback == null) return
        if (isActivityNotActive(activity)) {
            mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_ACTIVITY_DESTROYED)
            return
        }
        if (!isAdLoadSuccess()) {
            mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_ACTIVITY_DESTROYED)
            destroy()
            return
        }
        if (isAdShowing()) {
            mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_AD_IS_SHOWING)
            return
        }
    }

    open fun destroy() {
        timeout = 0
        realUnitId = ""
        timeoutDisposable?.dispose()
        timeoutDisposable = null
        countDownDisposable?.dispose()
        countDownDisposable = null
        isAdLoadSuccess = false
        isAdSDKCallback = false
        mOnLoadAdCallback = null
    }


    /**
     * 统计错误原因
     */
    protected fun analysisErrorCode(adInfo: AdInfo?, code: Int) {

    }


    fun isActivityNotActive(activity: Activity?): Boolean {
        return activity == null || activity.isFinishing || activity.isDestroyed
    }

    fun getAdmobErrorCode(errorCode: LoadAdError): Int {
        return if (errorCode.responseInfo?.adapterResponses.isNullOrEmpty()) { // 没有中介组
            Log.e("newAd", "没中介 -> " + errorCode.code)
            errorCode.code
        } else {
            val adAdapter = errorCode.responseInfo?.adapterResponses?.firstOrNull() ?: return -9999
            val adError = adAdapter.adError ?: return -9999
            val code = adError.code
            Log.e("newAd", "中介 -> " +  adAdapter.adapterClassName + ", " + code + ", msg=" + adError.message)
            code
        }
    }


    fun countDownInstreamAd(adRoot: ViewGroup) {
        val count = showTime.toLong() + 1
        countDownDisposable =
            Flowable.intervalRange(0, count, 0, 1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    val tvTime: TextView? = adRoot.findViewById(R.id.tvTime)
                    if (tvTime == null) {
                        mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_INTERNAL_ERROR)
                        destroy()
                        return@subscribe
                    }
                    tvTime.visibility = View.VISIBLE
                    tvTime.setOnClickListener(null)
                    tvTime.text = String.format("还剩(%d秒)跳过广告", (showTime - it))
                    if (it >= showTime.toLong() - 1) {
                        tvTime.setOnClickListener {
                            mOnLoadAdCallback?.onAdComplete()
                            countDownDisposable?.dispose()
                            destroy()
                        }

                        tvTime.text = "跳过广告"
                        if (it >= showTime.toLong()) { // 自动关闭
                            mOnLoadAdCallback?.onAdComplete()
                            countDownDisposable?.dispose()
                            destroy()
                        }
                    }
                }, {
                    it.printStackTrace()
                    countDownDisposable?.dispose()
                    mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_INTERNAL_ERROR)
                    destroy()
                })
    }

    fun countDownOpenAd(adRoot: ViewGroup) {
        val count = showTime.toLong() + 1
        countDownDisposable =
            Flowable.intervalRange(0, count, 0, 1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    val tvTime: TextView? = adRoot.findViewById(R.id.tvTime)
                    if (tvTime == null) {
                        mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_INTERNAL_ERROR)
                        destroy()
                        return@subscribe
                    }
                    tvTime.visibility = View.VISIBLE
                    tvTime.text = String.format("关闭(%d秒)", showTime - it)
                    if (it >= showTime) {
                        mOnLoadAdCallback?.onAdComplete()
                        destroy()
                    }
                    tvTime.setOnClickListener {
                        mOnLoadAdCallback?.onAdComplete()
                        countDownDisposable?.dispose()
                        destroy()
                    }
                }, {
                    it.printStackTrace()
                    countDownDisposable?.dispose()
                    mOnLoadAdCallback?.onAdLoadFailed(AdConstants.ERROR_CODE_INTERNAL_ERROR)
                    destroy()
                })
    }
}